# -*- coding: utf-8 -*-
import logging
import re
import time
import json
import requests
from datetime import datetime
from typing import Any, Dict, List, Text, Optional

from rasa_sdk import Action, Tracker
from rasa_sdk.forms import FormValidationAction
from rasa_sdk.executor import CollectingDispatcher
from rasa_sdk.events import (
    SlotSet,
    ActiveLoop,
    UserUtteranceReverted,
    ConversationPaused,
    EventType,
    FollowupAction,
)

from py2neo import Graph
import sys
import pymysql

from actions.api.chitbot_api import chitbot_api

logger = logging.getLogger(__name__)

#连接neo4j
try:
    graph = Graph(host="127.0.0.1", http_port=7474, user="neo4j", password="123456")
    print('neo4j连接上了')
except Exception as e:
    logger.error('Neo4j connection error: {}, check your Neo4j'.format(e))
    sys.exit(-1)
else:
    logger.debug('Neo4j Database connected successfully.')



#提供证件
class ActionDepartProductCertificate(Action):
    def name(self) -> Text:
        return "action_depart_product_certificate"

    def run(self,
            dispatcher: CollectingDispatcher,
            tracker: Tracker,
            domain: Dict[Text, Any]):

        product = tracker.get_slot('product')
        sql = "MATCH (m:product) where m.name = '{}'return m.Claims_information_required"
        certificate = graph.run(sql.format(product)).data()

        #是否为空
        try:
            if certificate[0]['m.Claims_information_required'] is not None:
                print_text = "{}产品所需要的理赔资料有：{} \n 请一定要记得带全噢~".format(product, certificate[0]['m.Claims_information_required'])
                print('================', product, certificate, print_text)
                dispatcher.utter_message(text=print_text)
                return [SlotSet("product", None)]
        except:
            # 如果product不是全名，查询包含product的相关保险名称
            try:
                sql = "MATCH (n:product) WHERE n.name =~ '.*{}.*' RETURN n.name LIMIT 10"
                category = graph.run(sql.format(product)).data()
                print('category1==',category)
                print_text = '非常抱歉，暂未查询到相关信息，您说的是如下产品吗？请您正确地输入一次，谢谢！(例如：xxx的保险类型是什么?)或者联系我们的人工客服，谢谢！'
                dispatcher.utter_message(text=print_text)
                str = ""
                for i in category:
                    text = i['n.name']
                    str += text+'\n'
                dispatcher.utter_message(text=str)
                return [SlotSet("product", None)]
            except:
                print_text = '非常抱歉，暂未查询到相关信息，如需帮助请联系我们的人工客服，谢谢！'
                dispatcher.utter_message(text=print_text)
                return [SlotSet("product", None)]

# 查产品类型
class ActionDepartProductCategory(Action):
    def name(self) -> Text:
        return "action_depart_product_category"

    def run(self,
            dispatcher: CollectingDispatcher,
            tracker: Tracker,
            domain: Dict[Text, Any]):
        product = tracker.get_slot('product')
        print(type(product))
        print(product)
        sql = "MATCH (m:product)-[r:belong_category]->(n:category) where m.name = '{}' return n.name"
        print('sql',sql)
        print(sql.format(product))
        print('=======================')
        category = graph.run(sql.format(product)).data()
        print(category)
        try:
            if category[0]['n.name'] is not None:
                print_text = "{}产品的类型为：{}".format(product, category[0]['n.name'])
                print('================', product, category, print_text)
                dispatcher.utter_message(text=print_text)
                return [SlotSet("product", None)]
        except:
            # 如果product不是全名，查询包含product的相关保险名称
            try:
                sql = "MATCH (n:product) WHERE n.name =~ '.*{}.*' RETURN n.name LIMIT 10"
                category = graph.run(sql.format(product)).data()
                print('category1==',category)
                print_text = '非常抱歉，暂未查询到相关信息，您说的是如下产品吗？请您正确地输入一次，谢谢！(例如：xxx的保险类型是什么?)或者联系我们的人工客服，谢谢！'
                dispatcher.utter_message(text=print_text)
                str = ""
                for i in category:
                    text = i['n.name']
                    str += text+'\n'
                dispatcher.utter_message(text=str)
                return [SlotSet("product", None)]
            except:
                print_text = '非常抱歉，暂未查询到相关信息，如需帮助请联系我们的人工客服，谢谢！'
                dispatcher.utter_message(text=print_text)
                return [SlotSet("product", None)]


#根据公司名称查询 附属产品
class ActionDepartCompanyProduct(Action):
    def name(self) -> Text:
        return "action_depart_company_product"

    def run(self,
            dispatcher: CollectingDispatcher,
            tracker: Tracker,
            domain: Dict[Text, Any]):
        company = tracker.get_slot('company')
        print(company)
        if company is not None:
            sql = "MATCH (m:product)-[r:belong_company]->(n:company) where n.name = '{}' return m.name LIMIT 10"
            print('sql',sql)
            print(sql.format(company))
            print('=======================')
            company_product = graph.run(sql.format(company)).data()
            print(company_product)
            if len(company_product) != 0:
                print_text = "{}的产品有:".format(company)
                print('================', company, company_product, print_text)
                dispatcher.utter_message(text=print_text)
                str = ""
                for i in company_product:
                    text = i['m.name']
                    str += text+'\n'
                dispatcher.utter_message(text=str)
                return [SlotSet("company", None)]
            else:
                print_text = '非常抱歉，暂未查询到相关信息，如需帮助请联系我们的人工客服，谢谢！'
                dispatcher.utter_message(text=print_text)
                return [SlotSet("company", None)]
        else:
            print_text = '非常抱歉，暂未查询到相关信息，如需帮助请联系我们的人工客服，谢谢！'
            dispatcher.utter_message(text=print_text)
            return [SlotSet("company", None)]


#查看公司具体信息
class ActionProductCompany(Action):
    def name(self) -> Text:
        return "action_depart_company_info"

    def run(self,
            dispatcher: CollectingDispatcher,
            tracker: Tracker,
            domain: Dict[Text, Any]):
        company = tracker.get_slot('company')
        print(company)
        if company is not None:
            sql = "MATCH (n:company) WHERE n.name ='{}' RETURN n.detail"
            print('sql',sql)
            print(sql.format(company))
            print('=======================')
            company_info = graph.run(sql.format(company)).data()
            print(company_info)
            try:
                if company_info[0]['n.detail'] is not None:
                    print_text = "{}的介绍：{}".format(company, company_info[0]['n.detail'])
                    print('================', company, company_info, print_text)
                    dispatcher.utter_message(text=print_text)
                    return [SlotSet("company", None)]

            except:
                print_text = '非常抱歉，暂未查询到相关信息，如需帮助请联系我们的人工客服，谢谢！'
                dispatcher.utter_message(text=print_text)
                return [SlotSet("company", None)]
        else:
            print_text = '非常抱歉，暂未查询到相关信息，如需帮助请联系我们的人工客服，谢谢！'
            dispatcher.utter_message(text=print_text)
            return [SlotSet("company", None)]
#闲聊
class ActionChitchat(Action):

    def name(self) -> Text:
        return "action_chitchat"

    def run(self, dispatcher: CollectingDispatcher,
            tracker: Tracker,
            domain: Dict[Text, Any],
            ) -> List[Dict[Text, Any]]:
        text = tracker.latest_message.get("text")
        answer = chitbot_api(text)
        print('问句:', text, '回复:', answer)
        dispatcher.utter_message(text=answer)

        return []


# 表单提交 information_form
class ActionSubmitInformationForm(Action):
    def name(self) -> Text:
        return "action_submit_information_form"

    def run(
            self,
            dispatcher: CollectingDispatcher,
            tracker: Tracker,
            domain: Dict[Text, Any],
    ) -> List[EventType]:
        """Once we have all the information, attempt to add it to the
        Google Drive database"""

        sex_1 = tracker.get_slot("sex_1")
        age_1 = tracker.get_slot("age_1")
        name_1 = tracker.get_slot("name_1")
        year_incoming_1 = tracker.get_slot("year_incoming_1")
        monthly_spending_1 = tracker.get_slot("monthly_spending_1")
        phone_num_1 = tracker.get_slot("phone_num_1")
        localtime = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
        print('date',localtime)
        print('=========year_incoming_1============')
        print('year_incoming', year_incoming_1)
        print('type_year', type(year_incoming_1))
        # sales_info = [sex_1, age_1, year_incoming_1,monthly_spending_1,phone_num_1, date]
        #计算保额
        if '万' in year_incoming_1:
            ret1 = re.findall('\d+',year_incoming_1)
            year_incoming_1 = int(ret1[0]) * 10000
        else:
            year_incoming_1 = int(year_incoming_1)
        if '万' in monthly_spending_1:
            ret2 = re.findall('\d+',monthly_spending_1)
            monthly_spending_1 = int(ret2[0]) * 10000
        else:
            monthly_spending_1 = int(monthly_spending_1)
        print('======2=================')
        print('year_incoming',year_incoming_1)
        print('type_year',type(year_incoming_1))
        sum_insured5 = year_incoming_1 * 5
        sum_insured10 = (year_incoming_1) * 10
        print('保额',sum_insured5,sum_insured10)

        #保存到mysql
        # 连接mysql
        connetct = pymysql.Connect(host='localhost',
                                   port=3306,
                                   user='root',
                                   passwd='root',
                                   db='insurance_chatbot',
                                   charset='utf8')
        print('mysql连接上了')
        #获取游标
        cursor = connetct.cursor()
        try:
            sql = "insert into information_form values" \
                  "(0,'{sex_1}','{age_1}','{name_1}','{year_incoming_1}','{monthly_spending_1}'," \
                  "'{phone_num_1}','{localtime}')".format(sex_1=sex_1,age_1=age_1,name_1=name_1,year_incoming_1=year_incoming_1,
                                                     monthly_spending_1=monthly_spending_1,phone_num_1=phone_num_1,
                                                     localtime=localtime)
            print('mysql_sql',sql)
            cursor.execute(sql)
            #提交结果
            connetct.commit()
        except Exception as e:
            print('mysql录入信息失败',e)
            #事务回滚，撤销前面的操作
            connetct.rollback()
        finally:
            #关闭数据库
            cursor.close()
            connetct.close()
        try:
            print('===============================================================')
            print_text1 = "您输入的信息如下：\n" \
                          "姓名：'{}'\n" \
                          "性别：'{}'\n" \
                          "年龄：'{}'\n" \
                          "电话：'{}'\n" \
                          "年收入：'{}'\n" \
                          "月消费：'{}'\n". \
                format(name_1, sex_1, age_1, phone_num_1, year_incoming_1, monthly_spending_1)
            dispatcher.utter_message(text=print_text1)
            print_text = "正在为您计算。。。\n" \
                         "给您的建议：重疾险保额为'{}'~'{}'元，意外险保额为‘{}'元。\n" \
                         "报销型险种：住院医疗，百万医疗以及意外医疗一定要补充哦！\n" \
                         "如果您资金有限请先补足以上保险类型哦！\n" \
                         "如果资金充裕补充完以上保险后还可考虑教育金、婚嫁金、创业金、养老规划、传承规划\n"\
                         "感谢您的咨询，稍后专业的保险顾问为您服务，请注意接听电话，谢谢！\n" \
                         "还有什么问题，请继续问我！".\
                format(sum_insured5,sum_insured10,sum_insured10)
            dispatcher.utter_message(text=print_text)
            return [SlotSet("sex_1", None), SlotSet("age_1", None),SlotSet("name_1", None),
                    SlotSet("year_incoming_1", None),SlotSet("monthly_spending_1", None),
                    SlotSet("phone_num_1", None)]
        except Exception as e:
            logger.error(
                "Failed to write data to gdocs. Error: {}" "".format(e.message),
                exc_info=True,
            )
            dispatcher.utter_message(template="utter_salesrequest_failed")
            return [SlotSet("sex_1", None), SlotSet("age_1", None), SlotSet("name_1", None),
                    SlotSet("year_incoming_1", None),
                    SlotSet("monthly_spending_1", None), SlotSet("phone_num_1", None)]


# 表单提交 information_form 填充无效值
# class ActionSubmitDeactiveInformationForm(Action):
#     def name(self) -> Text:
#         return "action_submit_deactive_information_form"
#
#     def run(
#             self,
#             dispatcher: CollectingDispatcher,
#             tracker: Tracker,
#             domain: Dict[Text, Any],
#     ) -> List[EventType]:
#         """Once we have all the information, attempt to add it to the
#         Google Drive database"""
#
#
#         return [SlotSet("sex_1", 1), SlotSet("age_1", 1), SlotSet("phone_num_1", 1)]
#

# # 表单提交 information_form
# class ActionInformationFormClear(Action):
#     def name(self) -> Text:
#         return "action_information_clear"
#
#     def run(
#             self,
#             dispatcher: CollectingDispatcher,
#             tracker: Tracker,
#             domain: Dict[Text, Any],
#     ) -> List[EventType]:
#         """Once we have all the information, attempt to add it to the
#         Google Drive database"""
#
#         return [SlotSet("sex_1", None), SlotSet("age_1", None), SlotSet("phone_num_1", None)]


# 表单失活
class ActionDeactivateLoop(Action):
    """Deactivates an active loop."""

    def name(self) -> Text:
        return "action_deactivate_loop"

    def run(
            self,
            dispatcher: CollectingDispatcher,
            tracker: Tracker,
            domain: Dict[Text, Any],
    ) -> List[EventType]:
        dispatcher.utter_message(template="utter_out")  # 恭喜你退出成功！有什么问题，请继续问我！
        """Runs action. Please see parent class for the full docstring."""
        return [ActiveLoop(None), SlotSet("sex_1", None), SlotSet("age_1", None), SlotSet("name_1", None),
                    SlotSet("year_incoming_1", None),
                    SlotSet("monthly_spending_1", None), SlotSet("phone_num_1", None)]


# 信息表单验证
class ValidateInformationForm(FormValidationAction):
    def name(self) -> Text:
        return "validate_information_form"

    # 验证性别
    def validate_sex_1(
            self,
            value: Text,
            dispatcher: CollectingDispatcher,
            tracker: Tracker,
            domain: Dict[Text, Any],
    ) -> Dict[Text, Any]:
        # 获取填写信息
        print(type(value))
        print('sex_vale', value)
        if value == '男' or value == '男士' or value =='帅哥' or value =='男的' or value =='南' or value =='南的':
            return {"sex_1": '男'}
        elif value == '女' or value == '女士' or value =='美女' or value =='女的':
            return {"sex_1": '女'}
        else:
            dispatcher.utter_message(template="utter_no_sex_1")
            return {"sex_1": None}

    # 验证年龄
    def validate_age_1(
            self,
            value: Text,
            dispatcher: CollectingDispatcher,
            tracker: Tracker,
            domain: Dict[Text, Any],
    ) -> Dict[Text, Any]:
        # 获取年龄信息
        try:
            print(type(value))
            print('age_vale', value)
            age = int(value)
            if age >= 0 and age < 120:
                return {"age_1": age}
            else:
                dispatcher.utter_message(template="utter_no_age_1")
                return {"age_1": None}
        except:
            dispatcher.utter_message(template="utter_no_age_1")
            return {"age_1": None}

    # 验证手机号
    def validate_phone_num_1(
            self,
            value: Text,
            dispatcher: CollectingDispatcher,
            tracker: Tracker,
            domain: Dict[Text, Any],
    ) -> Dict[Text, Any]:
        # 获取手机号
        print('phone_num_value', value)
        phone_num_1 = re.findall('^1[0-9]{10}$', str(value))
        print('phone_num_1', phone_num_1)
        if len(phone_num_1) != 0:
            return {"phone_num_1": value}
        else:
            dispatcher.utter_message(template="utter_no_phone_num_1")
            return {"phone_num_1": None}

#识别不了的意图，返回固定话术
class ActionDefaultFallback(Action):
    def name(self) -> Text:
        return "action_default_fallback"

    def run(
        self,
        dispatcher: CollectingDispatcher,
        tracker: Tracker,
        domain: Dict[Text, Any],
    ) -> List[EventType]:
        dispatcher.utter_message(template="utter_fallback")

        return []